/*!
 * 对象深拷贝模块
 * @author: __author__
 * @version: __buildVersion__
 * @buildDate：__buildDate__
 */

function isObject(obj: any): boolean {
    return Object.prototype.toString.call(obj) === '[object Object]';
}

//合并对象 （数组合并）
export function merge1(target: object, ...arg: any[]): object {
    return arg.reduce((acc: any, cur: any) => {
        if (cur === null || cur === undefined) {
            return acc;
        }

        return Object.keys(cur).reduce((subAcc: any, key: string) => {
            const srcVal = cur[key];

            if (isObject(srcVal) && isObject(subAcc[key])) {
                subAcc[key] = merge1(subAcc[key] ? subAcc[key] : {}, srcVal);
            } else if (Array.isArray(srcVal) && Array.isArray(subAcc[key])) {
                subAcc[key] = subAcc[key].concat(srcVal);
            } else {
                subAcc[key] = srcVal;
            }

            return subAcc;
        }, acc);
    }, target);
}

//合并对象 （数组替换）
export function merge2(target: object, ...arg: any[]): object {
    return arg.reduce((acc: any, cur: any) => {
        if (cur === null || cur === undefined) {
            return acc;
        }

        return Object.keys(cur).reduce((subAcc: any, key: string) => {
            const srcVal = cur[key];

            if (isObject(srcVal) && isObject(subAcc[key])) {
                subAcc[key] = merge(subAcc[key] ? subAcc[key] : {}, srcVal);
            } else if (Array.isArray(srcVal) && Array.isArray(subAcc[key])) {
                subAcc[key] = srcVal.map((item: any, idx: number) => {
                    if (isObject(item)) {
                        const curAccVal = subAcc[key] ? subAcc[key] : [];
                        return merge(
                            curAccVal[idx] ? curAccVal[idx] : {},
                            item
                        );
                    } else {
                        return item;
                    }
                });
            } else {
                subAcc[key] = srcVal;
            }

            return subAcc;
        }, acc);
    }, target);
}

const merge = merge1;
export default merge;